cmake_minimum_required (VERSION 3.22)


set(TOOLCHAIN_PATH "C:/toolchain/arm-none-eabi/bin")
set(ENV{PATH} "${TOOLCHAIN_PATH};$ENV{PATH}")
include("toolchain.cmake")

set(BIN_NAME wbctl)
project(${BIN_NAME} C CXX ASM)

option(EV_BUILD_TEST "Build unit tests in application" OFF)

set(SUPPORTED_BOARDS
    n32g45xvl_stb
    qimin407
)

set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
# set(CMAKE_CXX_EXTENSIONS OFF)
set(CMAKE_C_STANDARD 11)
set(CMAKE_C_STANDARD_REQUIRED ON)
# set(CMAKE_C_EXTENSIONS OFF)

# set the build type
if(NOT CMAKE_BUILD_TYPE)
    set(CMAKE_BUILD_TYPE Release)
endif()
if(CMAKE_BUILD_TYPE MATCHES Debug)
    message(STATUS "Board ${EV_BOARD} Debug build")
elseif(CMAKE_BUILD_TYPE MATCHES Release)
    message(STATUS "Board ${EV_BOARD} Release build")
else()
    message(FATAL_ERROR "Unknown build type: ${CMAKE_BUILD_TYPE}")
endif()
add_subdirectory(thirdparty/rtthread)
add_subdirectory(thirdparty/mbedtls)

file(GLOB_RECURSE EV_LIBRARY_SRCS library/*.c)
file(GLOB_RECURSE EV_BOOT_SRCS bootloader/*.c)
file(GLOB_RECURSE EV_APP_SRCS application/*.c)
list(FILTER EV_APP_SRCS EXCLUDE REGEX ".*unit_test.*")

function(add_board_targets BOARD_NAME)
    message(STATUS "Configuring build for board: ${BOARD_NAME}")
    add_subdirectory(board/${BOARD_NAME})
    set(APP_BIN_NAME ${BIN_NAME}_app_${BOARD_NAME})
    set(APP_SOURCES ${EV_APP_SRCS} ${EV_LIBRARY_SRCS})
    if(EV_BUILD_TEST)
        file(GLOB_RECURSE UNIT_TEST_SRCS application/unit_test/*.c)
        list(APPEND APP_SOURCES ${UNIT_TEST_SRCS})
    endif()
    add_executable(${APP_BIN_NAME} ${APP_SOURCES})
    if(EV_BUILD_TEST)
        target_compile_definitions(${APP_BIN_NAME} PRIVATE EV_BUILD_TEST)
    endif()
    target_link_libraries(${APP_BIN_NAME} PRIVATE
        driv_${BOARD_NAME}
        rtthread
        mbedtls
    )
    target_link_options(${APP_BIN_NAME} PRIVATE
        -T${CMAKE_CURRENT_SOURCE_DIR}/board/${BOARD_NAME}/script/app.ld
        -Wl,-Map=${CMAKE_CURRENT_BINARY_DIR}/${APP_BIN_NAME}.map
    )
    target_include_directories(${APP_BIN_NAME} PRIVATE
        application
        library
    )

    add_custom_command(TARGET ${APP_BIN_NAME} POST_BUILD
        COMMAND ${ARM_OBJCOPY_EXECUTABLE} -O binary
            $<TARGET_FILE:${APP_BIN_NAME}>
            $<TARGET_FILE_DIR:${APP_BIN_NAME}>/${APP_BIN_NAME}.bin
        COMMENT "Generating binary image: ${APP_BIN_NAME}.bin"
    )

    set(BOOT_BIN_NAME ${BIN_NAME}_boot_${BOARD_NAME})
    add_executable(${BOOT_BIN_NAME} ${EV_BOOT_SRCS} ${EV_LIBRARY_SRCS})

    target_link_libraries(${BOOT_BIN_NAME} PRIVATE
        driv_${BOARD_NAME}
        mbedtls
    )
    target_link_options(${BOOT_BIN_NAME} PRIVATE
        -T${CMAKE_CURRENT_SOURCE_DIR}/board/${BOARD_NAME}/script/boot.ld
        -Wl,-Map=${CMAKE_CURRENT_BINARY_DIR}/${BOOT_BIN_NAME}.map
    )
    target_include_directories(${BOOT_BIN_NAME} PRIVATE
        bootloader
        library
        board/${BOARD_NAME}/include
    )

    add_custom_command(TARGET ${BOOT_BIN_NAME} POST_BUILD
        COMMAND ${ARM_OBJCOPY_EXECUTABLE} -O binary
            $<TARGET_FILE:${BOOT_BIN_NAME}>
            $<TARGET_FILE_DIR:${BOOT_BIN_NAME}>/${BOOT_BIN_NAME}.bin
        COMMENT "Generating binary image: ${BOOT_BIN_NAME}.bin"
    )

    set_target_properties(${APP_BIN_NAME} ${BOOT_BIN_NAME}
        PROPERTIES FOLDER "boards/${BOARD_NAME}")

endfunction()

foreach(BOARD ${SUPPORTED_BOARDS})
    if(EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/board/${BOARD})
        add_board_targets(${BOARD})
    else()
        message(WARNING "Board directory not found: ${BOARD}")
    endif()
endforeach()

message(STATUS "")
message(STATUS "Build configuration summary:")
message(STATUS "  Project name: ${BIN_NAME}")
message(STATUS "  Build type: ${CMAKE_BUILD_TYPE}")
message(STATUS "  Unit tests: ${EV_BUILD_TEST}")
message(STATUS "")

if(SUPPORTED_BOARDS)
    list(GET SUPPORTED_BOARDS 0 DEFAULT_BOARD)
    add_custom_target(app
        COMMENT "Building application for default board: ${DEFAULT_BOARD}"
        DEPENDS ${BIN_NAME}_app_${DEFAULT_BOARD}
    )
    add_custom_target(boot
        COMMENT "Building bootloader for default board: ${DEFAULT_BOARD}"
        DEPENDS ${BIN_NAME}_boot_${DEFAULT_BOARD}
    )
endif()
